home *** CD-ROM | disk | FTP | other *** search
- /* CALL.c routines to do far calls and software interrupts from 'C
-
- Supports ISR article in Micro Cornucopia Magazine Issue #46
- */
-
-
- #include <call.h>
-
-
- /* SEG86
-
- This function simply copies the 8086 segment register contents
- into the __regs register structure pointed at by ri.
- */
-
- #pragma vpindex seg86
- unsigned int far seg86( ri )
- __regs far *ri;
- {
- #asm
- push es
- push es
- les bx, _RI
- pop ax
- mov _ES, ax
- mov _DS, ds
- mov _SS, ss
- mov _CS, cs
- pushf
- pop ax
- mov _PSW, ax
- pop es
- #endasm
- }
-
-
- /* CALL_8086()
-
- This function calls the code at _PC in *ri. It doesn't check
- for messed up stacks, but is reentrant.
- */
-
- #pragma vpindex call_8086
- unsigned int far call_8086( ri, ro )
- __regs far *ri, *ro;
- {
- #asm
- push si ;save 'C regs
- push di
- push ds
- push es
-
- les bx, _RI ;get pointer to input regs
-
- push bp ;we're going to need this later...
-
- push cs ;here's where the routine that we'll call
- mov ax, offset retadr
- push ax ;will return
-
- push _CS ;put address to call on the stack
- push _IP
-
- do_it: push _ES ;can't touch these now...
- push _BX ; so put them on the stack
-
- mov ax, _AX ;load up the cpu regs
- mov cx, _CX
- mov dx, _DX
- mov si, _SI
- mov di, _DI
- mov bp, _BP
- mov ds, _DS
- pop bx
- pop es
-
- ret ;do the call
-
- retadr: ;when the routine does a retf, we get here...
- push bp ;save the current bp
- mov bp, sp ;make it possible to get values off the stack
- mov bp, 2[bp] ;get the value of BP that we had before the call
-
- push es ;save the current value of ES
- push bx ; and BX
-
- les bx, _RO ;get a pointer to the output register structure
-
- mov _AX, ax ;save the current value of AX
- pop ax ;get the returned value of BX
- mov _BX, ax ; and save it too
- pop ax ;get ES
- mov _ES, ax ;save that...
- mov _CX, cx ;and this...
- mov _DX, dx
- mov _DS, ds
- mov _SI, si
- mov _DI, di
- pop ax ;then the BP that we last pushed
- mov _BP, ax
- pop ax ;...get rid of the BP that we pushed before that
- pushf ;and last but not least, save the flags...
- pop ax
- mov _PSW, ax
-
- pop es ;restore 'C regs
- pop ds
- pop di
- pop si
- #endasm
- }
-
-
- /* INTN_8086()
-
- This function calls the interrupt handler pointed at by
- element (IP) in the 8086 interrupt vector table.
- */
-
- #pragma vpindex intn_8086
- unsigned int far intn_8086( ri, ro )
- __regs far *ri, *ro;
- {
- #asm
- push si ;save 'C regs
- push di
- push ds
- push es
-
- push bp ;we're going to need this later...
-
- les bx, _RI ;get pointer to input regs
-
- pushf ;simulate an INT nn
- push cs ;here's where the routine that we'll call
- mov ax, offset retadr
- push ax ;will return
-
- mov ax, _IP ;interrupt number is hidden in _IP...
- shl ax, 1
- shl ax, 1
- cwd
- mov es, dx
- mov bx, ax
- push es:word ptr 2[bx] ;put address to call on the stack
- push es:word ptr 0[bx]
-
- les bx, _RI ;restore the es:bx pointer to _RI
- jmp do_it ;use the code in call_8086...
- #endasm
- }